package com.breaktian.network.http;

import android.annotation.TargetApi;
import android.content.Context;
import android.os.Build;

import com.breaktian.network.util.Utils;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.X509TrustManager;

import okhttp3.Interceptor;

/**
 * Created by keke.tian on 2018/4/3.
 */

public class HttpConfig {

    private static final int DEFAULT_TIMEOUT = 10;//单位是秒
    int connectTimeout = DEFAULT_TIMEOUT;
    int readTimeout = DEFAULT_TIMEOUT;
    int writeTimeout = DEFAULT_TIMEOUT;

    HttpHeader commonHeader = new HttpHeader();
    HttpParam commonParam = new HttpParam();

    private static HttpConfig mHttpConfig;

    public Context mContext;
    public boolean isDebug;

    SSLSocketFactory sslSocketFactory;
    X509TrustManager trustManager;
    HostnameVerifier hostnameVerifier;

    List<Interceptor> interceptors = new ArrayList<>();
    List<Interceptor> networkInterceptors = new ArrayList<>();


    private HttpConfig(){}

    public static HttpConfig getInstance(){
        if(mHttpConfig==null){
            synchronized (HttpConfig.class){
                if(mHttpConfig==null){
                    mHttpConfig = new HttpConfig();
                }
            }
        }
        return mHttpConfig;
    }

    public HttpConfig with(Context mContext) {
        this.mContext = mContext;
        return this;
    }


    public HttpConfig debug(boolean isDebug) {
        this.isDebug = isDebug;
        return this;
    }

    /**
     * Connection Timeout
     * @param connectTimeout 单位秒
     * @return
     */
    public HttpConfig connectTimeout(int connectTimeout) {
        this.connectTimeout = connectTimeout;
        return this;
    }

    /**
     * Read Timeout
     * @param readTimeout 单位秒
     * @return
     */
    public HttpConfig readTimeout(int readTimeout) {
        this.readTimeout = readTimeout;
        return this;
    }

    /**
     * Write Timeout
     * @param writeTimeout 单位秒
     * @return
     */
    public HttpConfig writeTimeout(int writeTimeout) {
        this.writeTimeout = writeTimeout;
        return this;
    }


    /**
     * 设置请求通用头
     * @param key
     * @param value
     * @return
     */
    public HttpConfig addCommonHeader(String key, String value) {
        commonHeader.add(key, value);
        return this;
    }

    /**
     * 设置请求通用头
     * @param headers
     * @return
     */
    public HttpConfig addCommonHeader(Map<String, String> headers) {
        commonHeader.merge(headers);
        return this;
    }

    /**
     * 设置请求通用参数
     * @param key
     * @param val
     * @return
     */
    public HttpConfig addCommonParam(String key, String val) {
        commonParam.add(key, val);
        return this;
    }


    public HttpConfig addInterceptor(Interceptor interceptor) {
        interceptors.add(interceptor);
        return this;
    }

    public HttpConfig addNetworkInterceptor(Interceptor interceptor) {
        networkInterceptors.add(interceptor);
        return this;
    }

    /**
     * https单向认证 用含有服务端公钥的证书校验服务端证书
     * @param certificates
     * @return
     */
    public HttpConfig certificates(InputStream... certificates) {
        return certificates(null, null, certificates);
    }

    /**
     * https双向认证
     * bksFile 和 password -> 客户端使用bks证书校验服务端证书
     * certificates -> 用含有服务端公钥的证书校验服务端证书
     * @param bksFile
     * @param password
     * @param certificates
     * @return
     */
    public HttpConfig certificates(InputStream bksFile, String password, InputStream... certificates) {
        Utils.SSLParams param = Utils.sslSocketFactory(null, bksFile, password, certificates);
        sslSocketFactory = param.sSLSocketFactory;
        trustManager = param.trustManager;
        return this;
    }

    /**
     * https单向认证
     * 可以额外配置信任服务端的证书策略，否则默认是按CA证书去验证的，若不是CA可信任的证书，则无法通过验证
     * @param trustManager
     * @return
     */
    public HttpConfig certificates(X509TrustManager trustManager) {
        return certificates(null, null, trustManager);
    }

    /**
     * https双向认证
     * bksFile 和 password -> 客户端使用bks证书校验服务端证书
     * X509TrustManager -> 如果需要自己校验，那么可以自己实现相关校验，如果不需要自己校验，那么传null即可
     * @param bksFile
     * @param password
     * @param trustManager
     * @return
     */
    public HttpConfig certificates(InputStream bksFile, String password, X509TrustManager trustManager) {
        Utils.SSLParams param = Utils.sslSocketFactory(trustManager, bksFile, password, null);
        sslSocketFactory = param.sSLSocketFactory;
        this.trustManager = param.trustManager;
        return this;
    }

    public HttpConfig hostnameVerifier() {
        return hostnameVerifier(new TrustHostnameVerifier());
    }

    public HttpConfig hostnameVerifier(HostnameVerifier hostnameVerifier) {
        this.hostnameVerifier = hostnameVerifier;
        return this;
    }

    class TrustHostnameVerifier implements HostnameVerifier {
        @Override
        public boolean verify(String hostname, SSLSession session) {
            return true;
        }
    }

}
